//
//  MetalView.m
//  OneToOne
//
//  Created by ByteDance on 2023/3/7.
//

#import "MetalView.h"
#import <Metal/Metal.h>
#import <MetalKit/MetalKit.h>
@import MetalKit;
@import GLKit;
@import AVFoundation;
@import CoreMedia;
#import <MetalPerformanceShaders/MetalPerformanceShaders.h>

@interface MetalView () <MTKViewDelegate>

@end

@implementation MetalView {
    id <MTLDevice> metalDevice;
    id <MTLCommandQueue> commandQueue;
    id <MTLTexture> texture;
    CVMetalTextureCacheRef _textureCache;
    MTKView *MtkView;
}

- (instancetype)init {
    self = [super init];
    if (self) {
    }
    return self;
}
- (void)viewDidLoad {
    [super viewDidLoad];
    metalDevice = MTLCreateSystemDefaultDevice();
    MtkView = [[MTKView alloc] initWithFrame:self.view.frame];
    MtkView.preferredFramesPerSecond = 15;
    MtkView.device = metalDevice;
    MtkView.delegate = self;
    MtkView.framebufferOnly = NO;
    commandQueue = [MtkView.device newCommandQueue];
    CVMetalTextureCacheCreate(NULL, NULL, MtkView.device, NULL, &_textureCache);
    [self.view addSubview:MtkView];
}
- (UIView *)getView {
    return self.view;
}
- (void)putInBuffer:(CVImageBufferRef)imageBuffer {
    if (imageBuffer == nil) {
        return;
    }
    CVPixelBufferLockBaseAddress(imageBuffer, 0);
    CVMetalTextureRef ref = [self acquireTextureFromBuffer: imageBuffer]; // PixelBuffer => CV Metal Texture
    texture = CVMetalTextureGetTexture(ref); // CV Metal Texture -> MTLTexture
    
    CVMetalTextureCacheFlush(_textureCache, 0); // 渲染完毕之后清空一下 texture cache

    CVPixelBufferUnlockBaseAddress(imageBuffer, 0);
    
    if (texture != NULL) { // 如果 texture 为 NULL，再 Release 就会出现 `EXC_BREAKPOINT` crash！
        //CFRelease((__bridge CFTypeRef)(texture)); // 没有这个，就会不再采集！！！！
    }
}
- (CVMetalTextureRef)acquireTextureFromBuffer: (CVPixelBufferRef)buffer {
    
    CVMetalTextureRef texture;
    CVReturn ret = CVMetalTextureCacheCreateTextureFromImage(kCFAllocatorDefault,
                                                             _textureCache,
                                                             buffer,
                                                             NULL,
                                                             MTLPixelFormatRGBA8Unorm,
                                                             CVPixelBufferGetWidth(buffer),
                                                             CVPixelBufferGetHeight(buffer),
                                                             0,
                                                             &texture);
    
    if (ret != kCVReturnSuccess) {
        NSLog(@"Read texture faild from sample buffer, %d", ret);
    }
    
    return texture;
}
- (void)drawInMTKView:(nonnull MTKView *)view {
    if (texture) {
        id<MTLCommandBuffer> commandBuffer = [commandQueue commandBuffer]; // 创建指令缓冲
        id<MTLTexture> drawingTexture = view.currentDrawable.texture; // 把MKTView作为目标纹理
        
        MPSImageGaussianBlur *filter = [[MPSImageGaussianBlur alloc] initWithDevice:MtkView.device sigma:0]; // 这里的sigma值可以修改，sigma值越高图像越模糊
        [filter encodeToCommandBuffer:commandBuffer sourceTexture:texture destinationTexture:drawingTexture]; // 把摄像头返回图像数据的原始数据
        
        [commandBuffer presentDrawable:view.currentDrawable]; // 展示数据
        [commandBuffer commit];
        
        texture = NULL;
    }
}

- (void)mtkView:(nonnull MTKView *)view drawableSizeWillChange:(CGSize)size {
    
}



@end
